package com.f1ussh.serviceuser.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.f1ussh.common.config.ConvertUtils;
import com.f1ussh.common.result.Result;
import com.f1ussh.serviceuser.dto.PageDTO;
import com.f1ussh.serviceuser.dto.UserCreateDTO;
import com.f1ussh.serviceuser.dto.UserQueryDTO;
import com.f1ussh.serviceuser.dto.UserUpdateDTO;
import com.f1ussh.serviceuser.entity.User;
import com.f1ussh.serviceuser.exception.ServiceUserException;
import com.f1ussh.serviceuser.mapper.UserMapper;
import com.f1ussh.serviceuser.service.UserService;
import com.f1ussh.common.result.PageResult;
import com.f1ussh.serviceuser.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @Author: 马腾飞
 * @CreateTime: 2025-10-01
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Result<PageResult<UserVO>> selectUserPage(PageDTO pageDTO, UserQueryDTO queryDTO) {

        try {
            //构建分页参数
            Page<User> page = new Page<>(pageDTO.getPage(), pageDTO.getSize());

            //构造查询条件


            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getIsDeleted, 0);
            if (StringUtils.hasText(queryDTO.getUsername())) {
                wrapper.like(User::getUsername, queryDTO.getUsername());
            }
            if (StringUtils.hasText(queryDTO.getNickname())) {
                wrapper.like(User::getNickname, queryDTO.getNickname());
            }
            if (StringUtils.hasText(queryDTO.getPhone())) {
                wrapper.like(User::getPhone, queryDTO.getPhone());
            }
            if (StringUtils.hasText(queryDTO.getEmail())) {
                wrapper.like(User::getEmail, queryDTO.getEmail());
            }
            if (queryDTO.getStatus() != null) {
                wrapper.eq(User::getStatus, queryDTO.getStatus());
            }
            if (queryDTO.getUserType() != null) {
                wrapper.eq(User::getUserType, queryDTO.getUserType());
            }
            // 执行分页查询
            Page<User> userPage = userMapper.selectPage(page, wrapper);

            List<UserVO> userVOS = ConvertUtils.convertList(userPage.getRecords(), UserVO.class);

            PageResult<UserVO> pageResult = PageResult.of(
                    userPage.getTotal(),
                    pageDTO.getPage(),
                    pageDTO.getSize(),
                    userVOS
            );
            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("方法：selectUserPage，查询失败：", e);
            return Result.error("查询用户列表失败");
        }

    }

    @Override
    public Result<UserVO> selectUserById(Long id) {
        try {
            UserVO userVO = ConvertUtils.convert(userMapper.selectById(id), UserVO.class);
            return Result.success(userVO);
        } catch (Exception e) {
            log.error("方法：selectUserById，查询失败：", e);
            return Result.error("查询用户失败");
        }
    }

    @Override
    public Result register(UserCreateDTO userDTO) {
        try {

            // 1. 唯一性验证
            validateUserUniqueness(userDTO);

            // 2. 密码加密
            String encodedPassword = passwordEncoder.encode(userDTO.getPassword());
            userDTO.setPassword(encodedPassword);

            // 3. 插入用户数据
            userMapper.insert(ConvertUtils.convert(userDTO, User.class));
            return Result.success("用户注册成功");

        } catch (ServiceUserException e) {
            log.warn("用户注册失败：{}", e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("方法：register，用户注册失败：", e);
            // 处理数据库唯一约束异常（兜底保护）
            if (isDuplicateKeyException(e)) {
                return Result.error("用户信息已存在，请检查手机号、邮箱或用户名");
            }
            return Result.error("系统错误，注册失败");
        }
    }

    /**
     * 统一验证用户唯一性
     */
    private void validateUserUniqueness(UserCreateDTO userDTO) {
        // 验证用户名唯一性
        if (existsUsername(userDTO.getUsername())) {
            throw new ServiceUserException("账号已存在");
        }

        // 验证手机号唯一性（如果提供了手机号）
        if (StringUtils.hasText(userDTO.getPhone())) {
            if (existsPhone(userDTO.getPhone())) {
                throw new ServiceUserException("手机号已被注册");
            }
        }

        // 验证邮箱唯一性（如果提供了邮箱）
        if (StringUtils.hasText(userDTO.getEmail())) {
            if (existsEmail(userDTO.getEmail())) {
                throw new ServiceUserException("邮箱已被注册");
            }
        }
    }


    @Override
    public boolean existsPhone(String phoneNumber) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(User::getPhone, phoneNumber)
                .eq(User::getIsDeleted, 0);

        return userMapper.exists(queryWrapper);

    }

    @Override
    public boolean existsEmail(String email) {
        return userMapper.exists(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email)
                .eq(User::getIsDeleted, 0));
    }

    @Override
    public boolean existsUsername(String username) {
        return userMapper.exists(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .eq(User::getIsDeleted, 0));
    }

    /**
     * 判断是否为数据库唯一约束异常（兜底处理）
     */
    private boolean isDuplicateKeyException(Exception e) {
        // MyBatis-Plus 的异常
        if (e instanceof DuplicateKeyException) {
            return true;
        }

        // Spring 的异常包装
        Throwable cause = e.getCause();
        while (cause != null) {
            if (cause instanceof DuplicateKeyException) {
                return true;
            }
            cause = cause.getCause();
        }

        // MySQL 重复键异常信息判断
        String message = e.getMessage();
        return message != null && (
                message.contains("Duplicate entry") ||
                        message.contains("唯一约束") ||
                        message.contains("unique constraint")
        );
    }

    /**
     * 更新用户信息
     *
     * @param userId userDTO
     * @return
     */
    @Override
    public Result updateUser(Long userId, UserUpdateDTO updateDTO) {
        try {
            System.out.println("🔧 开始更新用户: " + userId);

            // 1. 验证用户是否存在
            User existingUser = userMapper.selectById(userId);
            if (existingUser == null) {
                return Result.error("用户不存在");
            }

            // 2. 验证唯一性（只在字段变化时验证）
            if (StringUtils.hasText(updateDTO.getEmail()) &&
                    !updateDTO.getEmail().equals(existingUser.getEmail())) {
                if (existsEmail(updateDTO.getEmail())) {
                    return Result.error("邮箱已被使用");
                }
            }

            if (StringUtils.hasText(updateDTO.getPhone()) &&
                    !updateDTO.getPhone().equals(existingUser.getPhone())) {
                if (existsPhone(updateDTO.getPhone())) {
                    return Result.error("手机号已被使用");
                }
            }

            // 3. 使用 UpdateWrapper - 只更新 DTO 中提供的字段
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId);

            boolean hasUpdate = false;

            if (StringUtils.hasText(updateDTO.getPassword())) {
                String encryptedPassword = passwordEncoder.encode(updateDTO.getPassword());
                updateWrapper.set(User::getPassword, encryptedPassword);
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateDTO.getEmail())) {
                updateWrapper.set(User::getEmail, updateDTO.getEmail());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateDTO.getPhone())) {
                updateWrapper.set(User::getPhone, updateDTO.getPhone());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateDTO.getNickname())) {
                updateWrapper.set(User::getNickname, updateDTO.getNickname());
                hasUpdate = true;
            }

            // 4. 如果没有要更新的字段，直接返回
            if (!hasUpdate) {
                return Result.success("数据无变化");
            }

            // 5. 执行更新 - 只会更新上面设置的字段
            int result = userMapper.update(null, updateWrapper);
            return Result.success("更新成功");

        } catch (Exception e) {
            return Result.error("系统异常: " + e.getMessage());
        }
    }


}
